package ch.bfh.abcmmh.view;

import java.awt.Dimension;
import java.awt.Point;
import java.awt.SplashScreen;
import java.awt.Toolkit;
import java.util.Observable;
import java.util.Observer;

import ch.bfh.abcmmh.controller.operating.LogicController;
import ch.bfh.abcmmh.model.streetutils.Street;
import ch.bfh.abcmmh.view.controlview.ControlPanel;
import ch.bfh.abcmmh.view.detailview.Cars.GVehicle;
import ch.bfh.abcmmh.view.fullview.scopepanel.ScopePanel;
import ch.bfh.abcmmh.view.main.MainFrame;
import ch.bfh.abcmmh.view.main.StartupFrame;

public class GUIController implements Observer {

	private Dimension dim;
	private int x, y;
	private Point loc;
	private LogicController lctrl;
	private MainFrame mainFrame;
	private SplashScreen splashScreen;
	private float divisor;
	private int controlPanelHeight, fullPanelHeight, detailPanelHeight,
			logicalStreetLenth, width, height, dpos;
	private ControlPanel controlPanel;
	private ScopePanel scopePanel;
	private GVehicle followedVehicle;
	private StartupFrame startupFrame;

	public GUIController(LogicController lctrl) {
		this.lctrl = lctrl;
		startupFrame = new StartupFrame(lctrl, this);
	}

	public void setupGui() {
		this.logicalStreetLenth = lctrl.getStreetlength();
		this.controlPanelHeight = 100;
		this.detailPanelHeight = 400;
		this.fullPanelHeight = 200;
		this.width = 1400;
		this.height = (this.controlPanelHeight + this.fullPanelHeight + this.detailPanelHeight);
		this.dim = new Dimension(width, height);
		x = (int) (Toolkit.getDefaultToolkit().getScreenSize().getWidth() - width) / 2;
		y = (int) (Toolkit.getDefaultToolkit().getScreenSize().getHeight() - height) / 2;
		lctrl.setEntranceRamp(startupFrame.getEntranceRampCheckBox().isSelected());
		this.loc = new Point(x, y);
		this.setupMainframe();
	}

	public ScopePanel getScopePanel() {
		return scopePanel;
	}

	public ControlPanel getControlPanel() {
		return controlPanel;
	}

	public void setScopePanel(ScopePanel scopePanel) {
		this.scopePanel = scopePanel;
	}

	private void setupMainframe() {
		lctrl.addObservertoClock(this);
		controlPanel = new ControlPanel(this);
		mainFrame = new MainFrame(lctrl, this, controlPanel);
	}

	public void update(Observable o, Object obj) {
		followVehicle();
		controlPanel.repaintMe();
		if (mainFrame.getHistoryFrame() != null) {
			mainFrame.getHistoryFrame().repaint();
		}
		setControllpanelData();

	}

	private void followVehicle() {
		if (followedVehicle != null) {
			if (!followedVehicle.getVehicle().isOnStreet()) {
				followedVehicle.getVehicle().setObserved(false);
				followedVehicle = null;
			} else {
				int y = scopePanel.getY();
				int x = (int) (followedVehicle.getVehicle().getPosition() / divisor);
				x -= scopePanel.getWidth() / 2;
				if (x > 0 && x < getWidth() - scopePanel.getWidth()) {
					Point scopePoint = new Point(x, y);
					scopePanel.setLocation(scopePoint);
					scopePanel.calculateStreetArrayPositionofScope();
				}
			}
		}
	}

	public MainFrame getMainFrame() {
		return mainFrame;
	}

	private void setControllpanelData() {
		int avgDivisor = 0;
		int calcCycles = lctrl.getCalcCycles();
		int carCount = lctrl.getVehiclePool().getAllCars().size();
		int busCount = lctrl.getVehiclePool().getAllBuses().size();
		int truckCount = lctrl.getVehiclePool().getAllTrucks().size();
		int avgSpeed = lctrl.getVehiclePool().getAverageSpeedofCars();
		avgSpeed += lctrl.getVehiclePool().getAverageSpeedofBuses();
		avgSpeed += lctrl.getVehiclePool().getAverageSpeedofTrucks();
		float vehiclesPerSec = lctrl.getVehiclesPerSecond();
		controlPanel.setCarCount(carCount);
		controlPanel.setBusCount(busCount);
		controlPanel.setTruckCount(truckCount);
		controlPanel.setVehicleCount(carCount + busCount + truckCount);
		if (carCount > 0)
			avgDivisor++;
		if (busCount > 0)
			avgDivisor++;
		if (truckCount > 0)
			avgDivisor++;
		if (avgSpeed > 0) {
			if (avgDivisor == 0)
				avgDivisor = 1;
			controlPanel.setAvgSpeed(avgSpeed / avgDivisor);
		}
		controlPanel.setCalcCycles(calcCycles);
		controlPanel.setVehiclesPerSec(vehiclesPerSec);
	}

	public Dimension getMainFrameDimension() {
		return dim;
	}

	public Point getMainFrameLocation() {
		return loc;
	}

	public LogicController getLogicController() {
		return lctrl;
	}

	public int getStreetCount() {
		return lctrl.getCountofStreets();
	}

	public SplashScreen getSplashScreen() {
		return splashScreen;
	}

	public int getControlStreetPanelHeight() {
		return controlPanelHeight;
	}

	public int getDetailStreetPanelHeight() {
		return detailPanelHeight;
	}

	public int getFullStreetPanelHeight() {
		return fullPanelHeight - 23;
	}

	public int getWidth() {
		return width;
	}

	public void setDetailPosition(int dpos) {
		this.dpos = dpos;
		this.mainFrame.positionChanged();
	}

	public int getDetailPosition() {
		return dpos;
	}

	public int getLogicalStreetLenth() {
		return logicalStreetLenth;
	}

	public void setDivisor(float divisor) {
		this.divisor = divisor;
	}

	public float getDivisor() {
		return divisor;
	}

	public void repaintFullViewPanel() {
		this.mainFrame.getFullviewPanel().updateAllStreetSequences();
	}

	public GVehicle getFollowedVehicle() {
		return followedVehicle;
	}

	public void setFollowedVehicle(GVehicle followedvVehicle) {
		this.followedVehicle = followedvVehicle;
	}

	public Street getStreet(int streetNr) {
		return lctrl.getStreetGenerator().getStreet(streetNr);
	}
}